feat(tr-env): add TR-ENV-005, cnf.jwk must carry no private key material - #98
Merged
Merged
Conversation
GHSA-vc4p-h84j-7qxj, the trace-tests half. This repo carries a third copy of the Trust Record schema with the same gap trace-spec had: nothing constrained private JWK members, so a record publishing the key that signed it validated. The conformance suite did not catch it either. TR-ENV-004 checks that cnf.jwk.kty is present, and a record carrying `d` satisfies that, so it passed the whole suite. A conformance suite that passes a record which leaks its own signing key is worse than no check, because the pass is what a producer will cite. Adds the schema constraint and TR-ENV-005 as a distinct code rather than folding it into 004: presence of kty and absence of private material are different requirements, and a consumer reading a report should be able to tell which one failed. The finding names every member it found, since a producer needs to know what leaked. RFC 8747 makes cnf a confirmation key, the public half, present so a verifier can bind the record to the key that signed it. A record is signed, self-authenticating and usually anchored, so a key exposed this way must be treated as compromised. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XbDBXDWWvMFa7c2jGgyq9t
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The trace-tests half of GHSA-vc4p-h84j-7qxj. Pairs with agentrust-io/trace-spec#296, which fixes the two schema copies in that repo.
Two gaps here
The schema copy.
schemas/trace-claim.jsonis a third copy of the Trust Record schema and had the same hole: thecnf.jwkblock constrained only thekty/crv/x/yshapes, and everything else fell throughadditionalProperties. A record carrying its own private key validated.The suite itself.
TR-ENV-004checks thatcnf.jwk.ktyis present. A record carryingdsatisfies that, so it passed the whole conformance suite.That second one is the part worth fixing carefully. A conformance suite that passes a record which publishes its own signing key is worse than having no check, because the pass is what a producer will cite.
Why RFC 8747 makes this a real finding
cnfis a confirmation key: the public half, present so a verifier can bind the record to the key that signed it. There is no attacker step involved, and that is not a mitigation. A Trust Record is signed, self-authenticating and typically anchored, so once it is out the key is out and the identity has to be revoked.TR-ENV-005
Added as a distinct code rather than folded into 004. Presence of
ktyand absence of private material are different requirements, and someone reading a conformance report should be able to tell which one failed. The finding names every member it found, because a producer needs to know exactly what leaked.Covers the seven members
d,p,q,dp,dq,qi,k— the same set as_JWK_PRIVATE_PARAMSin theagentrust-tracereference model, which has always refused them on the producer side.Documented in
docs/error-codes.mdanddocs/modules/tr-env.md.Tests
Ten in
test_tr_env.py: one per private member, one that the message names every member found, and one that an ordinary public JWK still passes. One of them asserts thatTR-ENV-004still passes on a leaking record, which is the whole reason 005 had to exist as its own code.Reverting
tr_env.pyturns all eight private-material tests red.Full suite: 553 passed, 5 xpassed.
Note on the local environment
Collection fails in this repo's
.venvwithModuleNotFoundError: No module named 'rfc8785'on a clean checkout ofmain, before any change here. Installing it locally gives the run above. Worth a look separately — CI installs from the pin, so this is a local venv drift rather than a repo problem.🤖 Generated with Claude Code
https://claude.ai/code/session_01XbDBXDWWvMFa7c2jGgyq9t